package com.tjbklx1.threadpool;

//import com.dianping.cat.status.StatusExtension;
//import com.dianping.cat.status.StatusExtensionRegister;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 包装ThreadPoolExecutor
 */
public class ThreadPoolExecutorExtend extends ThreadPoolExecutor {

	/**
	 * 线程池名字
	 */
	private String threadPoolName;

	/**
	 * 实例计数器
	 */
	private static AtomicInteger newNumber = new AtomicInteger();

	/**
	 * 需要处理的任务数
	 */
	final AtomicInteger submittedTasksCount = new AtomicInteger();

	private long preCompletedTaskCount = -1;
	private long lastCalTime = -1;

	ThreadPoolExecutorExtend(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
			RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
		newNumber.getAndIncrement();
		// StatusExtensionRegister.getInstance().register(this);
	}

	/**
	 * 获取当前线程池正在执行的任务数
	 * 
	 * @return
	 */
	public AtomicInteger getSubmittedTasksCount() {

		return this.submittedTasksCount;
	}

	// 重写execute方法
	@Override
	public void execute(Runnable command) {
		submittedTasksCount.incrementAndGet();
		super.execute(command);
	}

	@SuppressWarnings("rawtypes")
	@Override
	protected void afterExecute(Runnable r, Throwable t) {
		// 执行完毕减1
		submittedTasksCount.decrementAndGet();

		if (r instanceof CommonFutureTask) {
			IAsynchronousHandler handler = ((CommonFutureTask) r).getAsynchronousHandler();
			if (handler == null) {
				throw new NullPointerException("线程池参数对象为null!");
			}

			handler.executeAfter(t);

		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	protected void beforeExecute(Thread t, Runnable r) {

		if (r instanceof CommonFutureTask) {
			IAsynchronousHandler handler = ((CommonFutureTask) r).getAsynchronousHandler();
			if (handler == null) {
				throw new NullPointerException("线程池参数对象为null!");
			}

			handler.executeBefore(t);

		}
	}

	@Override
	protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
		// TODO Auto-generated method stub
		return new CommonFutureTask<T>(callable);
	}

	@Override
	public String toString() {
		return "ThreadPoolExecutor: ActiveCount = " + this.getActiveCount() + " CompletedTaskCount = " + this.getCompletedTaskCount() + " CorePoolSize = " + this.getCorePoolSize()
				+ " LargestPoolSize = " + this.getLargestPoolSize() + " MaximumPoolSize = " + this.getMaximumPoolSize() + " PoolSize = " + this.getPoolSize() + " queueSize = " + this.getQueue().size()
				+ " queueString=[" + this.getQueue().toString() + "]";
	}

	// @Override
	public String getId() {
		return "ThreadPool";
	}

	// @Override
	public String getDescription() {
		return "ThreadPool info";
	}

	// @Override
	public Map<String, String> getProperties() {

		Map<String, String> map = new HashMap<String, String>();
		if ("base-framework-threadPool-".equals(threadPoolName)) {
			return map;
		}
		try {
			map.put(threadPoolName + "_submittedTasksCount", String.valueOf(getCompletedTasksRecently()));
			map.put(threadPoolName + "_activeCount", String.valueOf(super.getActiveCount()));
			map.put(threadPoolName + "_poolsize", String.valueOf(super.getPoolSize()));
			map.put(threadPoolName + "_maxPoolsize", String.valueOf(super.getMaximumPoolSize()));
			map.put(threadPoolName + "_queuesize", String.valueOf(super.getQueue().size()));
			return map;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

	public void setThreadPoolName(String threadPoolName) {
		if (StringUtils.isEmpty(threadPoolName)) {
			threadPoolName = "ThreadPoolExecutorExtend_" + newNumber.get();
		}
		this.threadPoolName = threadPoolName;
	}

	private long getCompletedTasksRecently() {
		if (preCompletedTaskCount == -1) {
			preCompletedTaskCount = super.getCompletedTaskCount();
			lastCalTime = System.currentTimeMillis();
			return 0;
		}
		long curCompletedTaskCount = super.getCompletedTaskCount();
		long count = curCompletedTaskCount - preCompletedTaskCount;

		long curCalTime = System.currentTimeMillis();
		long delta = curCalTime - lastCalTime;

		preCompletedTaskCount = curCompletedTaskCount;
		lastCalTime = curCalTime;

		return count * 1000 / delta;
	}
}
